<!DOCTYPE html>
<html lang="zh"
>
<head>
    <title>Python量化交易平台开发教程系列8-顶层GUI界面开发（2） - vn.py</title>
    <!-- Using the latest rendering mode for IE -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">


    <link href="/images/favicon.png" rel="icon">

<link rel="canonical" href="/basic-tutorial-8.html">

        <meta name="author" content="用Python的交易员" />
        <meta name="description" content="原创文章，转载请注明出处：用Python的交易员 前言 接上一篇，主要分为两块：展示动态语言特性简化GUI开发的组件以及功能调用组件。 动态语言的方便之处 ######################################################################## class AccountMonitor(QtGui.QTableWidget): &#34;&#34;&#34;用于显示账户&#34;&#34;&#34; signal = QtCore.pyqtSignal(type(Event())) dictLabels = OrderedDict() dictLabels[&#39;AccountID&#39;] = u&#39;投资者账户&#39; dictLabels[&#39;PreBalance&#39;] = u&#39;昨结&#39; dictLabels[&#39;Withdraw&#39;] = u&#39;出金&#39; dictLabels[&#39;Deposit&#39;] = u&#39;入金&#39; dictLabels[&#39;FrozenCash&#39;] = u&#39;冻结资金&#39; dictLabels[&#39;FrozenMargin&#39;] = u&#39;冻结保证金&#39; dictLabels[&#39;FrozenCommission&#39;] = u&#39;冻结手续费&#39; dictLabels[&#39;FrozenTransferFee ..." />

        <meta property="og:site_name" content="vn.py" />
        <meta property="og:type" content="article"/>
        <meta property="og:title" content="Python量化交易平台开发教程系列8-顶层GUI界面开发（2）"/>
        <meta property="og:url" content="/basic-tutorial-8.html"/>
        <meta property="og:description" content="原创文章，转载请注明出处：用Python的交易员 前言 接上一篇，主要分为两块：展示动态语言特性简化GUI开发的组件以及功能调用组件。 动态语言的方便之处 ######################################################################## class AccountMonitor(QtGui.QTableWidget): &#34;&#34;&#34;用于显示账户&#34;&#34;&#34; signal = QtCore.pyqtSignal(type(Event())) dictLabels = OrderedDict() dictLabels[&#39;AccountID&#39;] = u&#39;投资者账户&#39; dictLabels[&#39;PreBalance&#39;] = u&#39;昨结&#39; dictLabels[&#39;Withdraw&#39;] = u&#39;出金&#39; dictLabels[&#39;Deposit&#39;] = u&#39;入金&#39; dictLabels[&#39;FrozenCash&#39;] = u&#39;冻结资金&#39; dictLabels[&#39;FrozenMargin&#39;] = u&#39;冻结保证金&#39; dictLabels[&#39;FrozenCommission&#39;] = u&#39;冻结手续费&#39; dictLabels[&#39;FrozenTransferFee ..."/>
        <meta property="article:published_time" content="2015-07-14" />
            <meta property="article:section" content="文章" />
            <meta property="article:author" content="用Python的交易员" />


    <!-- Bootstrap -->
        <link rel="stylesheet" href="/theme/css/bootstrap.readable.min.css" type="text/css"/>
    <link href="/theme/css/font-awesome.min.css" rel="stylesheet">

    <link href="/theme/css/pygments/monokai.css" rel="stylesheet">
    <link rel="stylesheet" href="/theme/css/style.css" type="text/css"/>


        <script>
            var _hmt = _hmt || [];
            (function() {
              var hm = document.createElement("script");
              hm.src = "//hm.baidu.com/hm.js?e8c7573f82d43fa50c895a8e28c49ceb";
              var s = document.getElementsByTagName("script")[0]; 
              s.parentNode.insertBefore(hm, s);
            })();
        </script>

</head>
<body>

<div class="navbar navbar-default navbar-fixed-top" role="navigation">
	<div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a href="/" class="navbar-brand">
<img src="/images/favicon.png" width=""/> vn.py            </a>
        </div>
        <div class="collapse navbar-collapse navbar-ex1-collapse">
            <ul class="nav navbar-nav">
                         <li><a href="/pages/quickstart.html">
                             Quick Start
                          </a></li>
                         <li><a href="/pages/tutorial.html">
                             教程
                          </a></li>
                         <li><a href="/pages/blog.html">
                             日志
                          </a></li>
                         <li><a href="/pages/screenshot.html">
                             截图
                          </a></li>
                         <li><a href="/pages/community.html">
                             社区
                          </a></li>
                         <li><a href="/pages/api.html">
                             API接口
                          </a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
              <li><a href="/archives.html"><i class="fa fa-th-list"></i><span class="icon-label">Archives</span></a></li>
            </ul>
        </div>
        <!-- /.navbar-collapse -->
    </div>
</div> <!-- /.navbar -->
<!-- Banner -->
<style>
	#banner{
	    background-image:url("/images/banner.png");
	}
</style>

<div id="banner">
	<div class="container">
		<div class="copy">
			<h1>vn.py</h1>
				<p class="intro">Developed by traders, for traders.</p>
		</div>
	</div>
</div><!-- End Banner -->
<div class="container">
    <div class="row">
        <div class="col-sm-9">

    <section id="content">
        <article>
            <header class="page-header">
                <h1>
                    <a href="/basic-tutorial-8.html"
                       rel="bookmark"
                       title="Permalink to Python量化交易平台开发教程系列8-顶层GUI界面开发（2）">
                        Python量化交易平台开发教程系列8-顶层GUI界面开发（2）
                    </a>
                </h1>
            </header>
            <div class="entry-content">
                <div class="panel">
                    <div class="panel-body">
<footer class="post-info">
    <span class="label label-default">Date</span>
    <span class="published">
        <i class="fa fa-calendar"></i><time datetime="2015-07-14T13:20:00+08:00"> 2015-07-14(周二)</time>
    </span>



    
</footer><!-- /.post-info -->                    </div>
                </div>
                <p>原创文章，转载请注明出处：用Python的交易员</p>
<h2>前言</h2>
<p>接上一篇，主要分为两块：展示动态语言特性简化GUI开发的组件以及功能调用组件。</p>
<h2>动态语言的方便之处</h2>
<div class="highlight"><pre><span></span><span class="c1">########################################################################</span>
<span class="k">class</span> <span class="nc">AccountMonitor</span><span class="p">(</span><span class="n">QtGui</span><span class="o">.</span><span class="n">QTableWidget</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;用于显示账户&quot;&quot;&quot;</span>
    <span class="n">signal</span> <span class="o">=</span> <span class="n">QtCore</span><span class="o">.</span><span class="n">pyqtSignal</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">Event</span><span class="p">()))</span>

    <span class="n">dictLabels</span> <span class="o">=</span> <span class="n">OrderedDict</span><span class="p">()</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;AccountID&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;投资者账户&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;PreBalance&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;昨结&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;Withdraw&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;出金&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;Deposit&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;入金&#39;</span>    
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;FrozenCash&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;冻结资金&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;FrozenMargin&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;冻结保证金&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;FrozenCommission&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;冻结手续费&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;FrozenTransferFee&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;冻结过户费&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;FrozenStampTax&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;冻结印花税&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;Commission&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;手续费&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;TransferFee&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;过户费&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;StampTax&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;印花税&#39;</span>    
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;CurrMargin&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;当前保证金&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;Available&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;可用资金&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;WithdrawQuota&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;可取资金&#39;</span>

    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">eventEngine</span><span class="p">,</span> <span class="n">parent</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Constructor&quot;&quot;&quot;</span>
        <span class="nb">super</span><span class="p">(</span><span class="n">AccountMonitor</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">parent</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__eventEngine</span> <span class="o">=</span> <span class="n">eventEngine</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">dictAccount</span> <span class="o">=</span> <span class="p">{}</span>       <span class="c1"># 用来保存账户对应的单元格</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">initUi</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">registerEvent</span><span class="p">()</span>

    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">initUi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;&quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">setWindowTitle</span><span class="p">(</span><span class="s1">u&#39;账户&#39;</span><span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">setColumnCount</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dictLabels</span><span class="p">))</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">setHorizontalHeaderLabels</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dictLabels</span><span class="o">.</span><span class="n">values</span><span class="p">())</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">verticalHeader</span><span class="p">()</span><span class="o">.</span><span class="n">setVisible</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>                 <span class="c1"># 关闭左边的垂直表头</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">setEditTriggers</span><span class="p">(</span><span class="n">QtGui</span><span class="o">.</span><span class="n">QTableWidget</span><span class="o">.</span><span class="n">NoEditTriggers</span><span class="p">)</span> <span class="c1"># 设为不可编辑状态</span>

    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">registerEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;&quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">signal</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">updateAccount</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__eventEngine</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">EVENT_ACCOUNT</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">signal</span><span class="o">.</span><span class="n">emit</span><span class="p">)</span>

    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">updateAccount</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;&quot;&quot;&quot;</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">dict_</span><span class="p">[</span><span class="s1">&#39;data&#39;</span><span class="p">]</span>
        <span class="n">accountid</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;AccountID&#39;</span><span class="p">]</span>

        <span class="c1"># 如果之前已经收到过这个账户的数据, 则直接更新</span>
        <span class="k">if</span> <span class="n">accountid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dictAccount</span><span class="p">:</span>
            <span class="n">d</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dictAccount</span><span class="p">[</span><span class="n">accountid</span><span class="p">]</span>

            <span class="k">for</span> <span class="n">label</span><span class="p">,</span> <span class="n">cell</span> <span class="ow">in</span> <span class="n">d</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
                <span class="n">cell</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">label</span><span class="p">]))</span>
        <span class="c1"># 否则插入新的一行，并更新</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">insertRow</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
            <span class="n">d</span> <span class="o">=</span> <span class="p">{}</span>

            <span class="k">for</span> <span class="n">col</span><span class="p">,</span> <span class="n">label</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dictLabels</span><span class="o">.</span><span class="n">keys</span><span class="p">()):</span>
                <span class="n">cell</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QTableWidgetItem</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">label</span><span class="p">]))</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">setItem</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">col</span><span class="p">,</span> <span class="n">cell</span><span class="p">)</span>
                <span class="n">d</span><span class="p">[</span><span class="n">label</span><span class="p">]</span> <span class="o">=</span> <span class="n">cell</span>

            <span class="bp">self</span><span class="o">.</span><span class="n">dictAccount</span><span class="p">[</span><span class="n">accountid</span><span class="p">]</span> <span class="o">=</span> <span class="n">d</span>
</pre></div>


<p>写过C++里Qt代码的人可能会有比较直观的感受，上面这段代码利用Python动态语言的特性偷了不少懒。</p>
<p>该账户监控组件AccountMonitor用于显示LTS账户相关的数据（可用资金、手续费、保证金等等）。在vn.lts的API封装中，通过onRspQryTradingAccount推送回来的账户数据已经被从C++结构体自动转换为了Python字典。</p>
<div class="highlight"><pre><span></span><span class="c1">########################################################################</span>
<span class="k">class</span> <span class="nc">AccountMonitor</span><span class="p">(</span><span class="n">QtGui</span><span class="o">.</span><span class="n">QTableWidget</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;用于显示账户&quot;&quot;&quot;</span>
    <span class="n">signal</span> <span class="o">=</span> <span class="n">QtCore</span><span class="o">.</span><span class="n">pyqtSignal</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">Event</span><span class="p">()))</span>

    <span class="n">dictLabels</span> <span class="o">=</span> <span class="n">OrderedDict</span><span class="p">()</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;AccountID&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;投资者账户&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;PreBalance&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;昨结&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;Withdraw&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;出金&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;Deposit&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;入金&#39;</span>    
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;FrozenCash&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;冻结资金&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;FrozenMargin&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;冻结保证金&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;FrozenCommission&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;冻结手续费&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;FrozenTransferFee&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;冻结过户费&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;FrozenStampTax&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;冻结印花税&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;Commission&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;手续费&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;TransferFee&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;过户费&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;StampTax&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;印花税&#39;</span>    
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;CurrMargin&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;当前保证金&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;Available&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;可用资金&#39;</span>
    <span class="n">dictLabels</span><span class="p">[</span><span class="s1">&#39;WithdrawQuota&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">u&#39;可取资金&#39;</span>
</pre></div>


<p>首先通过原生API的.h头文件查询该结构体包含的字段内容，并选择觉得有用、需要显示出来的字段，使用Python内置的排序字典类OrderedDict创建标签显示的配置dictLabels，按照我们希望显示的顺序（从左到右）逐条输入到该字典中。字典的键是该字段的英文名称，值是该字段对应的中文名称。</p>
<div class="highlight"><pre><span></span>    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">initUi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;&quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">setWindowTitle</span><span class="p">(</span><span class="s1">u&#39;账户&#39;</span><span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">setColumnCount</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dictLabels</span><span class="p">))</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">setHorizontalHeaderLabels</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dictLabels</span><span class="o">.</span><span class="n">values</span><span class="p">())</span>
</pre></div>


<p>下一步在初始化表格时，表头的列数可以直接取dictLabels的长度，表头的标签内容可以直接取dictLabels的值列表。</p>
<div class="highlight"><pre><span></span>    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">updateAccount</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;&quot;&quot;&quot;</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">dict_</span><span class="p">[</span><span class="s1">&#39;data&#39;</span><span class="p">]</span>
        <span class="n">accountid</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;AccountID&#39;</span><span class="p">]</span>

        <span class="c1"># 如果之前已经收到过这个账户的数据, 则直接更新</span>
        <span class="k">if</span> <span class="n">accountid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dictAccount</span><span class="p">:</span>
            <span class="n">d</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dictAccount</span><span class="p">[</span><span class="n">accountid</span><span class="p">]</span>

            <span class="k">for</span> <span class="n">label</span><span class="p">,</span> <span class="n">cell</span> <span class="ow">in</span> <span class="n">d</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
                <span class="n">cell</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">label</span><span class="p">]))</span>
        <span class="c1"># 否则插入新的一行，并更新</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">insertRow</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
            <span class="n">d</span> <span class="o">=</span> <span class="p">{}</span>

            <span class="k">for</span> <span class="n">col</span><span class="p">,</span> <span class="n">label</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dictLabels</span><span class="o">.</span><span class="n">keys</span><span class="p">()):</span>
                <span class="n">cell</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QTableWidgetItem</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">label</span><span class="p">]))</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">setItem</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">col</span><span class="p">,</span> <span class="n">cell</span><span class="p">)</span>
                <span class="n">d</span><span class="p">[</span><span class="n">label</span><span class="p">]</span> <span class="o">=</span> <span class="n">cell</span>

            <span class="bp">self</span><span class="o">.</span><span class="n">dictAccount</span><span class="p">[</span><span class="n">accountid</span><span class="p">]</span> <span class="o">=</span> <span class="n">d</span>
</pre></div>


<p>在更新账户数据时，由于dictLabels中设置的需要显示的字段和收到的账户数据字典data中的键是一一对应的，我们可以直接对dictLabels中的键进行遍历读取data字典中对应的值，并更新到表格中。这段感觉比较难以用语言描述出来，直接读懂上面的代码可能更能明白其中的意思。</p>
<p>可以来比较下updateAccount函数的类C++的写法，也是作者在刚开始做GUI开发时使用的方法，现在回看起来真是繁琐。</p>
<div class="highlight"><pre><span></span>    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">updateAccount</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;&quot;&quot;&quot;</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">dict_</span><span class="p">[</span><span class="s1">&#39;data&#39;</span><span class="p">]</span>
        <span class="n">accountid</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;AccountID&#39;</span><span class="p">]</span>

        <span class="c1"># 如果之前已经收到过这个账户的数据, 则直接更新</span>
        <span class="k">if</span> <span class="n">accountid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dictAccount</span><span class="p">:</span>
            <span class="n">d</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dictAccount</span><span class="p">[</span><span class="n">accountid</span><span class="p">]</span>

            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;AccountID&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;AccountID&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;PreBalance&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;PreBalance&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;Deposit&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;Deposit&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;FrozenCash&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;FrozenCash&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;FrozenMargin&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;FrozenMargin&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;FrozenCommission&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;FrozenCommission&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;FrozenTransferFee&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;FrozenTransferFee&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;FrozenStampTax&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;FrozenStampTax&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;Commission&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;Commission&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;TransferFee&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;TransferFee&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;StampTax&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;StampTax&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;CurrMargin&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;CurrMargin&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;Available&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;Available&#39;</span><span class="p">]))</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;WithdrawQuota&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;WithdrawQuota&#39;</span><span class="p">]))</span>

        <span class="c1"># 否则插入新的一行，并更新</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">insertRow</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
            <span class="n">d</span> <span class="o">=</span> <span class="p">{}</span>

            <span class="n">cellAccountID</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QTableWidgetItem</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;AccountID&#39;</span><span class="p">]))</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">setItem</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">cellAccountID</span><span class="p">)</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;AccountID&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">cell</span>

            <span class="n">cellPreBalance</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QTableWidgetItem</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;PreBalance&#39;</span><span class="p">]))</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">setItem</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">cellPreBalance</span><span class="p">)</span>
            <span class="n">d</span><span class="p">[</span><span class="s1">&#39;PreBalance&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">cell</span>

            <span class="o">...</span>
            <span class="err">（后面的字段以此类推，这里请原谅作者实在不想写下去了，习惯遍历后复制粘贴都觉得麻烦）</span>

            <span class="bp">self</span><span class="o">.</span><span class="n">dictAccount</span><span class="p">[</span><span class="n">accountid</span><span class="p">]</span> <span class="o">=</span> <span class="n">d</span>
</pre></div>


<p>和上面的类C++写法相比，之前Python写法的优势就很明显了：</p>
<ul>
<li>
<p>代码行数显著减少（绝大部分都是重复内容），降低了coding时出错的概率，省下很多debug的时间</p>
</li>
<li>
<p>dictLabels可以直接作为配置来使用（类似于Java中使用很多配置文件），当需要增加或者移除某个字段时，用户只需更改dictLabels中的内容而无需改变initUi和updateAccount（这才是浪费无数debug时间的地方），同时修改的配置和本身的程序代码一样都是Python源代码文件（不像Java使用XML等其他文件进行配置）</p>
</li>
</ul>
<p>当然也存在一个缺点：理论上list遍历的使用降低了性能（GUI的更新耗时更长），但是作者以一个实际用户的经验可以告诉大家，这个性能上的牺牲微乎其微，考虑到vn.py的应用场景，这个缺点几乎可以忽略。</p>
<p>（限于作者本身的C++水平，以上这段编程语言的比较可能有不正确之处，欢迎读者指出。）</p>
<h2>功能调用组件</h2>
<div class="highlight"><pre><span></span><span class="c1">########################################################################</span>
<span class="k">class</span> <span class="nc">LoginWidget</span><span class="p">(</span><span class="n">QtGui</span><span class="o">.</span><span class="n">QDialog</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;登录&quot;&quot;&quot;</span>

    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mainEngine</span><span class="p">,</span> <span class="n">parent</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Constructor&quot;&quot;&quot;</span>
        <span class="nb">super</span><span class="p">(</span><span class="n">LoginWidget</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__mainEngine</span> <span class="o">=</span> <span class="n">mainEngine</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">initUi</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">loadData</span><span class="p">()</span>

    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">initUi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;初始化界面&quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">setWindowTitle</span><span class="p">(</span><span class="s1">u&#39;登录&#39;</span><span class="p">)</span>

        <span class="c1"># 设置组件</span>
        <span class="n">labelUserID</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLabel</span><span class="p">(</span><span class="s1">u&#39;账号：&#39;</span><span class="p">)</span>
        <span class="n">labelMdPassword</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLabel</span><span class="p">(</span><span class="s1">u&#39;行情密码：&#39;</span><span class="p">)</span>
        <span class="n">labelTdPassword</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLabel</span><span class="p">(</span><span class="s1">u&#39;交易密码：&#39;</span><span class="p">)</span>
        <span class="n">labelMdAddress</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLabel</span><span class="p">(</span><span class="s1">u&#39;行情服务器：&#39;</span><span class="p">)</span>
        <span class="n">labelTdAddress</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLabel</span><span class="p">(</span><span class="s1">u&#39;交易服务器：&#39;</span><span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">editUserID</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLineEdit</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">editMdPassword</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLineEdit</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">editTdPassword</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLineEdit</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">editMdAddress</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLineEdit</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">editTdAddress</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QLineEdit</span><span class="p">()</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">editUserID</span><span class="o">.</span><span class="n">setMinimumWidth</span><span class="p">(</span><span class="mi">200</span><span class="p">)</span>

        <span class="n">buttonLogin</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QPushButton</span><span class="p">(</span><span class="s1">u&#39;登录&#39;</span><span class="p">)</span>
        <span class="n">buttonCancel</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QPushButton</span><span class="p">(</span><span class="s1">u&#39;取消&#39;</span><span class="p">)</span>
        <span class="n">buttonLogin</span><span class="o">.</span><span class="n">clicked</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">login</span><span class="p">)</span>
        <span class="n">buttonCancel</span><span class="o">.</span><span class="n">clicked</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">)</span>

        <span class="c1"># 设置布局</span>
        <span class="n">buttonHBox</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QHBoxLayout</span><span class="p">()</span>
        <span class="n">buttonHBox</span><span class="o">.</span><span class="n">addStretch</span><span class="p">()</span>
        <span class="n">buttonHBox</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="n">buttonLogin</span><span class="p">)</span>
        <span class="n">buttonHBox</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="n">buttonCancel</span><span class="p">)</span>

        <span class="n">grid</span> <span class="o">=</span> <span class="n">QtGui</span><span class="o">.</span><span class="n">QGridLayout</span><span class="p">()</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="n">labelUserID</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="n">labelMdPassword</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="n">labelTdPassword</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="n">labelMdAddress</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="n">labelTdAddress</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editUserID</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editMdPassword</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editTdPassword</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editMdAddress</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addWidget</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editTdAddress</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="n">grid</span><span class="o">.</span><span class="n">addLayout</span><span class="p">(</span><span class="n">buttonHBox</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">setLayout</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span>

    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">login</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;登录&quot;&quot;&quot;</span>
        <span class="n">userid</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editUserID</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
        <span class="n">mdPassword</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editMdPassword</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
        <span class="n">tdPassword</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editTdPassword</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
        <span class="n">mdAddress</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editMdAddress</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
        <span class="n">tdAddress</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editTdAddress</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
        <span class="n">brokerid</span> <span class="o">=</span> <span class="s1">&#39;2011&#39;</span>    <span class="c1"># 这里因为LTS的BrokerID固定为2011</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">__mainEngine</span><span class="o">.</span><span class="n">login</span><span class="p">(</span><span class="n">userid</span><span class="p">,</span> <span class="n">mdPassword</span><span class="p">,</span> <span class="n">tdPassword</span><span class="p">,</span> <span class="n">brokerid</span><span class="p">,</span> <span class="n">mdAddress</span><span class="p">,</span> <span class="n">tdAddress</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">loadData</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;读取数据&quot;&quot;&quot;</span>
        <span class="n">f</span> <span class="o">=</span> <span class="n">shelve</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s1">&#39;setting.vn&#39;</span><span class="p">)</span>

        <span class="k">try</span><span class="p">:</span>
            <span class="n">setting</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">&#39;login&#39;</span><span class="p">]</span>
            <span class="n">userid</span> <span class="o">=</span> <span class="n">setting</span><span class="p">[</span><span class="s1">&#39;userid&#39;</span><span class="p">]</span>
            <span class="n">mdPassword</span> <span class="o">=</span> <span class="n">setting</span><span class="p">[</span><span class="s1">&#39;mdPassword&#39;</span><span class="p">]</span>
            <span class="n">tdPassword</span> <span class="o">=</span> <span class="n">setting</span><span class="p">[</span><span class="s1">&#39;tdPassword&#39;</span><span class="p">]</span>
            <span class="n">mdAddress</span> <span class="o">=</span> <span class="n">setting</span><span class="p">[</span><span class="s1">&#39;mdAddress&#39;</span><span class="p">]</span>
            <span class="n">tdAddress</span> <span class="o">=</span> <span class="n">setting</span><span class="p">[</span><span class="s1">&#39;tdAddress&#39;</span><span class="p">]</span>

            <span class="bp">self</span><span class="o">.</span><span class="n">editUserID</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="n">userid</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">editMdPassword</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="n">mdPassword</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">editTdPassword</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="n">tdPassword</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">editMdAddress</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="n">mdAddress</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">editTdAddress</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="n">tdAddress</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
            <span class="k">pass</span>

        <span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">saveData</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;保存数据&quot;&quot;&quot;</span>
        <span class="n">setting</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="n">setting</span><span class="p">[</span><span class="s1">&#39;userid&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editUserID</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
        <span class="n">setting</span><span class="p">[</span><span class="s1">&#39;mdPassword&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editMdPassword</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
        <span class="n">setting</span><span class="p">[</span><span class="s1">&#39;tdPassword&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editTdPassword</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
        <span class="n">setting</span><span class="p">[</span><span class="s1">&#39;mdAddress&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editMdAddress</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
        <span class="n">setting</span><span class="p">[</span><span class="s1">&#39;tdAddress&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">editTdAddress</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>

        <span class="n">f</span> <span class="o">=</span> <span class="n">shelve</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s1">&#39;setting.vn&#39;</span><span class="p">)</span>
        <span class="n">f</span><span class="p">[</span><span class="s1">&#39;login&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">setting</span>
        <span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

    <span class="c1">#----------------------------------------------------------------------</span>
    <span class="k">def</span> <span class="nf">closeEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;关闭事件处理&quot;&quot;&quot;</span>
        <span class="c1"># 当窗口被关闭时，先保存登录数据，再关闭</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">saveData</span><span class="p">()</span>
        <span class="n">event</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
</pre></div>


<ol>
<li>
<p>主动调用组件通常在工作原理上较为简单，用户只需在界面上放置所需的组件（按钮、下拉框等），并将组件的信号和中层引擎暴露的功能函数连接上（参考上面的initUi和login方法）</p>
</li>
<li>
<p>对于一些我们希望保存下来省去每次输入麻烦的信息，这里推荐Python的shelve库，可以直接将Python中的数据对象以二进制的方式保存在文件中（文件后缀名可以自行定义）</p>
</li>
<li>
<p>在登录组件第一次创建时，我们从硬盘上的setting.vn文件中尝试读取登录账号等设置内容，同时每次在关闭该窗口时closeEvent方法会被自动触发，保存当前文本框中的设置内容到文件中</p>
</li>
</ol>
<h2>总结</h2>
<p>系列7和8两篇教程中已经基本覆盖了GUI界面开发的核心原理，剩下的更多细节以及开发中的一些奇技淫巧就留给读者自己去研究vn.py项目的源代码了，毕竟对于这套教程的目标读者，有能力去开发适合自己交易策略的量化平台才是最终目标：now it's time to get your hands dirty。 </p>
<p>至此，Python量化交易平台开发教程系列告一段落，作者接下来会将更多的精力放在vn.py项目本身的开发上。同时vn.py的社区已经初具规模，QQ群已经逐渐不能满足大家交流的需求，针对Python量化交易开发的一个论坛也已经初步搭好，近期将会开放，欢迎大家入驻。</p>
            </div>
            <!-- /.entry-content -->
        </article>
    </section>

        </div>
        <div class="col-sm-3" id="sidebar">
            <aside>

<section class="well well-sm">
    <ul class="list-group list-group-flush">
            <li class="list-group-item"><h4><i class="fa fa-home fa-lg"></i><span class="icon-label">Social</span></h4>
              <ul class="list-group" id="social">
                <li class="list-group-item"><a href="http://github.com/vnpy/vnpy"><i class="fa fa-github-square fa-lg"></i> Github</a></li>
              </ul>
            </li>



    <li class="list-group-item"><h4><i class="fa fa-external-link-square fa-lg"></i><span class="icon-label">Links</span></h4>
      <ul class="list-group" id="links">
        <li class="list-group-item">
            <a href="http://www.vnpie.com" target="_blank">
                官方论坛 - 维恩的派
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.trader" target="_blank">
                交易平台
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.event" target="_blank">
                事件引擎
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.ctp" target="_blank">
                CTP接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.xspeed" target="_blank">
                飞创接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.femas" target="_blank">
                飞马接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="https://github.com/vnpy/vnpy/tree/master/vn.lts" target="_blank">
                LTS接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.ksotp" target="_blank">
                金仕达期权接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.ksgold" target="_blank">
                金仕达黄金接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.sgit" target="_blank">
                飞鼠接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/dev/vn.qdp" target="_blank">
                QDP接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.oanda" target="_blank">
                OANDA接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.ib" target="_blank">
                IB接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.shzd" target="_blank">
                直达期货接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.okcoin" target="_blank">
                OKCoin接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.datayes" target="_blank">
                通联数据接口
            </a>
        </li>
        <li class="list-group-item">
            <a href="http://github.com/vnpy/vnpy/tree/master/vn.demo" target="_blank">
                开发DEMO
            </a>
        </li>
      </ul>
    </li>
    </ul>
</section>
            </aside>
        </div>
    </div>
</div>
<footer>
   <div class="container">
      <hr>
      <div class="row">
         <div class="col-xs-10">&copy; 2017 用Python的交易员
            &middot; Powered by <a href="https://github.com/DandyDev/pelican-bootstrap3" target="_blank">pelican-bootstrap3</a>,
            <a href="http://docs.getpelican.com/" target="_blank">Pelican</a>,
            <a href="http://getbootstrap.com" target="_blank">Bootstrap</a>         </div>
         <div class="col-xs-2"><p class="pull-right"><i class="fa fa-arrow-up"></i> <a href="#">Back to top</a></p></div>
      </div>
   </div>
</footer>
<script src="/theme/js/jquery.min.js"></script>

<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/theme/js/bootstrap.min.js"></script>

<!-- Enable responsive features in IE8 with Respond.js (https://github.com/scottjehl/Respond) -->
<script src="/theme/js/respond.min.js"></script>

    <script src="/theme/js/bodypadding.js"></script>

</body>
</html>